#include "stdafx.h"
#include "LeftTimeDisplay.h"
#include "DPIForm.h"
#include "FontFactory.h"

IMPLEMENT_DYNAMIC(CLeftTimeDisplay, CTimeDisplay)

CLeftTimeDisplay::CLeftTimeDisplay()
{
	CFontFactory m_fFactory; HDC hScrDC = CreateScrDC();
	HFONT oldFont = (HFONT)::SelectObject(hNumMemDC, m_fFactory.Create(_T("Arial"), 38, 14, FW_BOLD)->GetLast());
	CSize szTime, szMs;
	for (int i = 0; i < 10; i++)
	{
		swprintf_s(nmMsRed[i].v, L"%d", i);
		::GetTextExtentPoint32(hNumMemDC, nmMsRed[i].v, 1, &nmMsRed[i].sz);
		nmMsRed[i].getSize(i, szMs);
	}
	for (intptr_t i = 0; i < 10; i++)
	{
		::SetTextColor(hNumMemDC, RGB(255, 0, 0));
		CPoint p((szMs.cx - nmMsRed[i].sz.cx) >> 1, (szMs.cy - nmMsRed[i].sz.cy) >> 1);
		drawNum(hScrDC, &nmMsRed[i], p, szMs);
		::SetTextColor(hNumMemDC, RGB(255, 255, 0)); nmMsYellow[i] = nmMsRed[i];
		drawNum(hScrDC, &nmMsYellow[i], p, szMs);
	}
	::SelectObject(hNumMemDC, m_fFactory.Create(_T("Arial"), 50, 18, FW_BOLD)->GetLast());
	for (int i = 0; i < 13; i++)
	{
		switch (i)
		{
		case 10:	wcscpy_s(nmTimeGreen[i].v, L"."); break;
		case 11:	wcscpy_s(nmTimeGreen[i].v, L":"); break;
		case 12:	wcscpy_s(nmTimeGreen[i].v, L"m"); break;
		default:	swprintf_s(nmTimeGreen[i].v, L"%d", i); break;
		}
		::GetTextExtentPoint32(hNumMemDC, nmTimeGreen[i].v, 1, &nmTimeGreen[i].sz);
		if (i < 10) nmTimeGreen[i].getSize(i, szTime);
	}
	for (intptr_t i = 0; i < 13; i++)
	{
		::SetTextColor(hNumMemDC, RGB(0, 255, 0));
		if (i < 10)
		{
			CPoint p((szTime.cx - nmTimeGreen[i].sz.cx) >> 1, (szTime.cy - nmTimeGreen[i].sz.cy) >> 1);
			drawNum(hScrDC, &nmTimeGreen[i], p, szTime);
			::SetTextColor(hNumMemDC, RGB(255, 0, 0)); nmTimeRed[i] = nmTimeGreen[i];
			drawNum(hScrDC, &nmTimeRed[i], p, szTime);
			::SetTextColor(hNumMemDC, RGB(255, 255, 0)); nmTimeYellow[i] = nmTimeGreen[i];
			drawNum(hScrDC, &nmTimeYellow[i], p, szTime);
		}
		else
		{
			CPoint p(0, 0);
			drawNum(hScrDC, &nmTimeGreen[i], p, nmTimeGreen[i].sz);
			if (i == 10)
			{
				::SetTextColor(hNumMemDC, RGB(255, 0, 0)); nmTimeRed[i] = nmTimeGreen[i];
				drawNum(hScrDC, &nmTimeRed[i], p, nmTimeRed[i].sz);
				::SetTextColor(hNumMemDC, RGB(255, 255, 0)); nmTimeYellow[i] = nmTimeGreen[i];
				drawNum(hScrDC, &nmTimeYellow[i], p, nmTimeYellow[i].sz);
			}
		}
	}
	CRect * numr[] = { numRect0, numRect1, numRect2, numRect3 };
	CSize sz[4];
	for (intptr_t st = 0; st < 4; st++)
	{
		intptr_t numCount = st == 0 || st == 3 ? 3 : 4;
		for (intptr_t i = 0, x = 0, y = 0; i < numCount; i++)
		{
			numr[st][i].left = (int)x; intptr_t n = -1;
			switch (st)
			{
			case 0:	//0.0-9.9
				if (i == 1) n = 10;
				break;
			case 1:	//10.0-59.9
				if (i == 2) n = 10;
				break;
			case 2:	//1:00-9:59
				if (i == 1) n = 11;
				break;
			case 3:	//10m-99m
				if (i == 2) n = 12;
				break;
			}
			if (n >= 0)
			{
				x += nmTimeGreen[n].sz.cx;
				numr[st][i].top = (int)(y + ((szTime.cy - nmTimeGreen[n].sz.cy) >> 1));
				numr[st][i].bottom = (int)(numr[st][i].top + nmTimeGreen[n].sz.cy);
			}
			else if ((st == 0 && i == 2) || (st == 1 && i == 3))
			{
				x += szMs.cx;
				numr[st][i].top = (int)(y + szTime.cy - szMs.cy - CDPIForm::DPIY(3));
				numr[st][i].bottom = (int)(numr[st][i].top + szMs.cy);
			}
			else
			{
				x += szTime.cx;
				numr[st][i].top = (int)y;
				numr[st][i].bottom = (int)(numr[st][i].top + szTime.cy);
			}
			sz[st].cx = numr[st][i].right = (int)x;
			if (i == 0 || sz[st].cy < numr[st][i].Height()) sz[st].cy = numr[st][i].Height();
		}
		if (st == 0)
		{
			width = sz[st].cx; height = sz[st].cy;
		}
		else
		{
			if (sz[st].cx>width) width = sz[st].cx;
			if (sz[st].cy>height) height = sz[st].cy;
		}
	}
	numRectNA = CRect(0, 0, (int)width, (int)height);
	hBitmapNA = drawNA(::CreateCompatibleBitmap(hScrDC, (int)width, (int)height));
	width += CDPIForm::DPIX(20); numRectNA.MoveToX((int)((width - numRectNA.Width()) >> 1));
	for (intptr_t st = 0; st < 4; st++)
	{
		intptr_t offx = (width - sz[st].cx) >> 1, offy = (height - sz[st].cy) >> 1;
		intptr_t numCount = st == 0 || st == 3 ? 3 : 4;
		for (intptr_t i = 0; i < numCount; i++) numr[st][i].OffsetRect((int)offx, (int)offy);
	}
	::SelectObject(hNumMemDC, oldFont);
	CreateMemBitmap(hScrDC, width, height);
	::DeleteDC(hScrDC);
	lfSec = -2; m_state = -2;
}

CLeftTimeDisplay::~CLeftTimeDisplay()
{
	for (intptr_t i = 0; i < 13; i++)
	{
		if (nmTimeGreen[i].bmp) ::DeleteObject(nmTimeGreen[i].bmp);
		if (i < 11 && nmTimeRed[i].bmp) ::DeleteObject(nmTimeRed[i].bmp);
		if (i < 11 && nmTimeYellow[i].bmp) ::DeleteObject(nmTimeYellow[i].bmp);
		if (i < 10 && nmMsRed[i].bmp) ::DeleteObject(nmMsRed[i].bmp);
		if (i < 10 && nmMsYellow[i].bmp) ::DeleteObject(nmMsYellow[i].bmp);
	}
	if (hBitmapNA) ::DeleteObject(hBitmapNA);
}

BEGIN_MESSAGE_MAP(CLeftTimeDisplay, CTimeDisplay)
END_MESSAGE_MAP()

void CLeftTimeDisplay::setLeftTime(intptr_t leftSeconds/*0.1s*/)
{
	if (leftSeconds == lfSec) return;
	lfSec = leftSeconds;
	if (lfSec < 0)
	{
		if (m_state == -1) return;
		m_state = -1; CTimeDisplay::drawOut(numRectNA, hBitmapNA);
		return;
	}
	intptr_t m = lfSec / 600, sec = (lfSec % 600) / 10, ms = lfSec % 10, st;
	if (m == 0)
		st = sec < 10 ? 0 : 1;
	else
	{
		if (ms)
		{
			sec++; if (sec >= 60) { m++; sec -= 60; }
		}
		if (m < 10)
			st = 2;
		else
		{
			if (sec) m++;
			if (m > 99) m = 99;
			st = 3;
		}
	}
	if (m_state != st)
	{
		m_state = st;
		::FillRect(hMemDC, CRect(0, 0, (int)width, (int)height), (HBRUSH)::GetStockObject(BLACK_BRUSH));
		switch (m_state)
		{
		case 0:
			for (intptr_t i = 0; i < 3; i++) { numRect[i] = numRect0[i]; numIndex[i] = -1; }
			drawOutRed(1, 10);
			break;
		case 1:
			for (intptr_t i = 0; i < 4; i++) { numRect[i] = numRect1[i]; numIndex[i] = -1; }
			drawOutYellow(2, 10);
			break;
		case 2:
			for (intptr_t i = 0; i < 4; i++) { numRect[i] = numRect2[i]; numIndex[i] = -1; }
			drawOutGreen(1, 11);
			break;
		case 3:
			for (intptr_t i = 0; i < 3; i++) { numRect[i] = numRect3[i]; numIndex[i] = -1; }
			drawOutGreen(2, 12);
			break;
		}
		Invalidate();
	}
	switch (m_state)
	{
	case 0:	//0.0-9.9
		if (numIndex[0] != sec) drawOutRed(0, sec);
		if (numIndex[2] != ms) drawMsRed(ms);
		break;
	case 1:	//10.0-59.9
	{
		intptr_t v = (intptr_t)(sec / 10) & 0xf; if (numIndex[0] != v) drawOutYellow(0, v);
		v = sec % 10; if (numIndex[1] != v) drawOutYellow(1, v);
		if (numIndex[3] != ms) drawMsYellow(ms);
	}	break;
	case 2:	//1:00-9:59
	{
		if (numIndex[0] != m) drawOutGreen(0, m);
		intptr_t v = (intptr_t)(sec / 10) & 0xf; if (numIndex[2] != v) drawOutGreen(2, v);
		v = sec % 10; if (numIndex[3] != v) drawOutGreen(3, v);
	}	break;
	case 3:	//10m-99m
	{
		intptr_t v = (intptr_t)(m / 10) & 0xf; if (numIndex[0] != v) drawOutGreen(0, v);
		v = m % 10; if (numIndex[1] != v) drawOutGreen(1, v);
	}	break;
	}
}

void CLeftTimeDisplay::drawOutGreen(intptr_t id, intptr_t n)
{
	numIndex[id] = n;
	if (n >= 0 && n < 13) CTimeDisplay::drawOut(numRect[id], nmTimeGreen[n].bmp);
}
void CLeftTimeDisplay::drawOutRed(intptr_t id, intptr_t n)
{
	numIndex[id] = n;
	if (n >= 0 && n < 11) CTimeDisplay::drawOut(numRect[id], nmTimeRed[n].bmp);
}
void CLeftTimeDisplay::drawOutYellow(intptr_t id, intptr_t n)
{
	numIndex[id] = n;
	if (n >= 0 && n < 11) CTimeDisplay::drawOut(numRect[id], nmTimeYellow[n].bmp);
}
void CLeftTimeDisplay::drawMsRed(intptr_t n)
{
	numIndex[2] = n;
	if (n >= 0 && n < 10) CTimeDisplay::drawOut(numRect[2], nmMsRed[n].bmp);
}
void CLeftTimeDisplay::drawMsYellow(intptr_t n)
{
	numIndex[3] = n;
	if (n >= 0 && n < 10) CTimeDisplay::drawOut(numRect[3], nmMsYellow[n].bmp);
}
